/*
 * unittest3.c
 * testGainCard
 *
 *  Created on: Jan 25, 2014
 *      Author: adam
 */

/* -----------------------------------------------------------------------
 * Demonstration of how to write unit tests for dominion-base
 * Include the following lines in your makefile:
 *
 * testUpdateCoins: testUpdateCoins.c dominion.o rngs.o
 *      gcc -o testUpdateCoins -g  testUpdateCoins.c dominion.o rngs.o $(CFLAGS)
 * -----------------------------------------------------------------------
 */

#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "rngs.h"

char* getCard(int cardNo);

int main() {
    int i; //loop counter
    int j; //loop counter
    int l; //loop counter
    int r; //initialization variable
    int a; //testing variable to confirm increments and decrements
    int b; //testing variable to confirm increments and decrements    
    int partialPass; //for compound tests
    int failcount = 0; //track tests passed
    int passcount = 0; //track tests failed
    int check; //holds result returned from test function
    int seed = 1000;
    int numPlayer = 2;
    int k[10] = {adventurer, council_room, feast, gardens, mine
               , remodel, smithy, village, baron, great_hall};
    struct gameState G;   

    printf("\nTesting GainCard():\n");

    //test empty pile (lower boundary, middle, upper boundary)
    printf("\nTesting empty pile at lower boundary, middle boundary and upper"
    		" boundary of list of cards:\n\n");
    for (i = curse; i <= treasure_map; i += 13){

        memset(&G, 23, sizeof(struct gameState));   // clear the game state
        r = initializeGame(numPlayer, k, seed, &G); // initialize a new game        

        for (j = curse; j <= treasure_map; j++){
            G.supplyCount[j] = 0;
        }

        printf("Testing empty pile for supply position %s.\n", getCard(i));
        check = gainCard(i, &G, 1, 1);
        printf("gainCard() returned: %d,  Expected -1\n", check);
        if (check == -1){
            printf("TEST PASSED\n\n");
            passcount++;
        }
        else {
            printf("TEST FAILED\n\n");
            failcount++;
        }
    }

    //test add to deck for both players (lower boundary, middle, upper boundary)
    printf("Testing add to deck at lower boundary, middle and upper"
    		" boundary of list of cards:\n\n");
    for (i = 0; i < numPlayer; i++){
        //test only boundary and middle cases
        for (j = curse; j <= treasure_map; j += 26){
            memset(&G, 23, sizeof(struct gameState));   // clear the game state
            r = initializeGame(numPlayer, k, seed, &G); // initialize a new game        

            //set partial pass monitor to true
            partialPass = 1;

            //populate all supply piles
            for (l = curse; l <= treasure_map; l++){
            G.supplyCount[l] = 1;            
            }   

            //store current deckCount and supplyCount for player for comparison
            a = G.deckCount[i];
            b = G.supplyCount[j];

            
            printf("Testing add \"%s\" to deck for player %d:\n", getCard(j), i);            
            assert(gainCard(j, &G, 1, i) == 0);
            check = G.deck[ i ][a]; //a used because gainCard() increments it           
            printf("gainCard() set last card in deck to: %s,  ",
            getCard(check));
            printf("Expected: %s\n", getCard(j));
            if (check != j){
                partialPass = 0;
            }

            printf("gaincard() incremented player's deck count to: %d,  ",
            check = G.deckCount[i]);
            printf("Expected: %d\n", (a + 1));
            if (check != a + 1){
                partialPass = 0;
            }

            check = G.supplyCount[j];
            printf("gainCard() decremented global count of \"%s\" cards to %d,  ",
                getCard(j), check);
            printf("Expected: %d\n", b - 1);
            if (check != b - 1){
                partialPass = 0;
            }

            if (partialPass == 1){
                printf("TEST PASSED\n\n");
                passcount++;
            }
            else {
                printf("TEST FAILED\n\n");
                failcount++;
            }

        }
    }


    //test add to hand (lower boundary, middle, upper boundary)
    printf("Testing add to hand at lower boundary, middle and upper"
    		" boundary of list of cards:\n\n");
    for (i = 0; i < numPlayer; i++){
        
        for (j = curse; j <= treasure_map; j += 13){
            memset(&G, 23, sizeof(struct gameState));   // clear the game state
            r = initializeGame(numPlayer, k, seed, &G); // initialize a new game        

            //set partial pass monitor to true
            partialPass = 1;

            //populate all supply piles
            for (l = curse; l <= treasure_map; l++){
            G.supplyCount[l] = 1;            
            }   

            //store current deckCount and supplyCount for player for comparison
            a = G.handCount[i];
            b = G.supplyCount[j];

            
            printf("Testing add \"%s\" to hand for player %d:\n", getCard(j), i);            
            assert(gainCard(j, &G, 2, i) == 0);
            check = G.hand[ i ][a]; //a used because gainCard() increments it           
            printf("gainCard() set last card in hand to: %s,  ",
            getCard(check));
            printf("Expected: %s\n", getCard(j));
            if (check != j){
                partialPass = 0;
            }

            printf("gaincard() incremented player's hand count to: %d,  ",
            check = G.handCount[i]);
            printf("Expected: %d\n", (a + 1));
            if (check != a + 1){
                partialPass = 0;
            }

            check = G.supplyCount[j];
            printf("gainCard() decremented global count of \"%s\" cards to %d,  ",
                getCard(j), check);
            printf("Expected: %d\n", b - 1);
            if (check != b - 1){
                partialPass = 0;
            }

            if (partialPass == 1){
                printf("TEST PASSED\n\n");
                passcount++;
            }
            else {
                printf("TEST FAILED\n\n");
                failcount++;
            }

        }
    }

    //test add to discard (lower boundary, middle, upper boundary)
    printf("Testing add to discard at lower boundary, middle and upper"
    		" boundary of list of cards:\n\n");
    for (i = 0; i < numPlayer; i++){
        
        for (j = curse; j <= treasure_map; j += 13){
            memset(&G, 23, sizeof(struct gameState));   // clear the game state
            r = initializeGame(numPlayer, k, seed, &G); // initialize a new game        

            //set partial pass monitor to true
            partialPass = 1;

            //populate all supply piles
            for (l = curse; l <= treasure_map; l++){
            G.supplyCount[l] = 1;            
            }   

            //store current deckCount and supplyCount for player for comparison
            a = G.discardCount[i];
            b = G.supplyCount[j];

            
            printf("Testing add \"%s\" to discard for player %d:\n", getCard(j), i);            
            assert(gainCard(j, &G, 0, i) == 0);
            check = G.discard[ i ][a]; //a used because gainCard() increments it           
            printf("gainCard() set last card in discard to: %s,  ",
            getCard(check));
            printf("Expected: %s\n", getCard(j));
            if (check != j){
                partialPass = 0;
            }

            printf("gaincard() incremented player's discard count to: %d,  ",
            check = G.discardCount[i]);
            printf("Expected: %d\n", (a + 1));
            if (check != a + 1){
                partialPass = 0;
            }

            check = G.supplyCount[j];
            printf("gainCard() decremented global count of \"%s\" cards to %d,  ",
                getCard(j), check);
            printf("Expected: %d\n", b - 1);
            if (check != b - 1){
                partialPass = 0;
            }

            if (partialPass == 1){
                printf("TEST PASSED\n\n");
                passcount++;
            }
            else {
                printf("TEST FAILED\n\n");
                failcount++;
            }

        }
    }

    //test boundary flags (-1 and 4, which are out of bounds, should both return -1 (invalid)
    printf("Testing lower and upper boundary (out of bounds) of flags:\n\n");

    //lower boundary (should return -1 due to invalid flag)
    memset(&G, 23, sizeof(struct gameState));   // clear the game state
    r = initializeGame(numPlayer, k, seed, &G); // initialize a new game        
    
    //populate all supply piles
    for (l = curse; l <= treasure_map; l++){
        G.supplyCount[l] = 1;            
    } 
    printf("Testing upper boundary using toFlag of -1:\n");
    check = gainCard(treasure_map, &G, -1, 1);
    printf("gainCard() returned %d, ", check);
    printf("Expected: -1 (invalid input)\n");
    if (check != 0){
        printf("TEST PASSED\n\n");
        passcount++;
    }
    else {
        printf("TEST FAILED\n\n");
        failcount++;
    }
      

    //test upper boundary (should return -1 for invalid flag)
    memset(&G, 23, sizeof(struct gameState));   // clear the game state
    r = initializeGame(numPlayer, k, seed, &G); // initialize a new game        
    
    //populate all supply piles
    for (l = curse; l <= treasure_map; l++){
        G.supplyCount[l] = 1;            
    } 
    
    printf("Testing lower boundary using toFlag of 4:\n");
    check = gainCard(treasure_map, &G, 4, 1);
    printf("gainCard() returned %d, ", check);
    printf("Expected: -1 (invalid input)\n");
    if (check != 0){
        printf("TEST PASSED\n\n");
        passcount++;
    }
    else {
        printf("TEST FAILED\n\n");
        failcount++;
    } 



    if (failcount == 0){
        printf("All tests passed!\n\n");
    }
    else{
        printf("%d tests failed. %d tests passed.\n", failcount, passcount);
        printf("Review log above for details.\n\n");
    }
    



    return 0;
}




char* getCard(int cardNo){
    if (cardNo == curse){
        return "curse";
    }
    if (cardNo == estate){
        return "estate";
    }
    if (cardNo == duchy){
        return "duchy";
    }
    if (cardNo == province){
        return "province";
    }
    if (cardNo == copper){
        return "copper";
    }
    if (cardNo == silver){
        return "silver";
    }
    if (cardNo == gold){
        return "gold";
    }
    if (cardNo == adventurer){
        return "adventurer";
    }
    if (cardNo == council_room){
        return "council_room";
    }
    if (cardNo == feast){
        return "feast";
    }
    if (cardNo == gardens){
        return "gardens";
    }
    if (cardNo == mine){
        return "mine";
    }
    if (cardNo == remodel){
        return "remodel";
    }
    if (cardNo == smithy){
        return "smithy";
    }
    if (cardNo == village){
        return "village";
    }
    if (cardNo == baron){
        return "baron";
    }
    if (cardNo == great_hall){
        return "great_hall";
    }
    if (cardNo == minion){
        return "minion";
    }
    if (cardNo == steward){
        return "steward";
    }
    if (cardNo == tribute){
        return "tribute";
    }
    if (cardNo == ambassador){
        return "ambassador";
    }
    if (cardNo == cutpurse){
        return "cutpurse";
    }
    if (cardNo == embargo){
        return "embargo";
    }
    if (cardNo == outpost){
        return "outpost";
    }
    if (cardNo == salvager){
        return "salvager";
    }
    if (cardNo == sea_hag){
        return "sea_hag";
    }
    if (cardNo == treasure_map){
        return "treasure_map";
    }
    return "fail";
}
